// PyOpenSG is (C) Copyright 2005-2009 by Allen Bierbaum
//
// This file is part of PyOpenSG.
//
// PyOpenSG is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version.
//
// PyOpenSG is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "osg_module/osgmodule_mainheader.h"
#include <OpenSG/OSGLine.h>
#include <OpenSG/OSGContainerPtrFuncs.h>
#include <boost/bind.hpp>
#include <boost/python.hpp>
#include "Wrappers.h"

namespace bp = boost::python;

namespace osgwrap
{

OSG::ActionBase::ResultE wrapEnterCallback(bp::object obj,
                                           OSG::Node::ObjRecPtr node)
{
   return bp::extract<OSG::ActionBase::ResultE>(obj(node));
}

OSG::ActionBase::ResultE wrapExitCallback(bp::object obj,
                                          OSG::Node::ObjRecPtr node,
                                          OSG::Action::ResultE result)
{
   return bp::extract<OSG::ActionBase::ResultE>(obj(node, result));
}

OSG::ActionBase::ResultE traverseWrapper1(OSG::Node::ObjRecPtr root,
                                          bp::object func)
{
   return OSG::traverse(root, boost::bind(wrapEnterCallback, func, _1));
}

OSG::ActionBase::ResultE traverseWrapper2(bp::list nodeList, bp::object func)
{
   const unsigned int node_count =
      bp::extract<unsigned int>(nodeList.attr("__len__")());
   std::vector<OSG::Node*> node_vec(node_count);

   for ( unsigned int i = 0; i < node_count; ++i )
   {
      OSG::NodeRecPtr cur_node = bp::extract<OSG::NodeRecPtr>(nodeList[i]);
      node_vec[i] = cur_node.get();
   }

   return OSG::traverse(node_vec, boost::bind(wrapEnterCallback, func, _1));
}

OSG::ActionBase::ResultE traverseWrapper3(OSG::Node::ObjRecPtr root,
                                          bp::object enterFunc,
                                          bp::object exitFunc)
{
   return OSG::traverse(root, boost::bind(wrapEnterCallback, enterFunc, _1),
                        boost::bind(wrapExitCallback, exitFunc, _1, _2));
}

OSG::ActionBase::ResultE traverseWrapper4(bp::list nodeList,
                                          bp::object enterFunc,
                                          bp::object exitFunc)
{
   const unsigned int node_count =
      bp::extract<unsigned int>(nodeList.attr("__len__")());
   std::vector<OSG::Node*> node_vec(node_count);

   for ( unsigned int i = 0; i < node_count; ++i )
   {
      OSG::NodeRecPtr cur_node = bp::extract<OSG::NodeRecPtr>(nodeList[i]);
      node_vec[i] = cur_node.get();
   }

   return OSG::traverse(node_vec,
                        boost::bind(wrapEnterCallback, enterFunc, _1),
                        boost::bind(wrapExitCallback, exitFunc, _1, _2));
}

//OSG::Int32 ptrGetRefCount(OSG::FieldContainerPtr ptr)
//{ return ptr.getRefCount(); }

//OSG::UInt32 ptrGetContainerId(OSG::FieldContainerPtr ptr)
//{ return OSG::getContainerId(ptr); }

bool osgInitWrapper(bp::list pythonArgv)
{
   const unsigned int argc =
      bp::extract<unsigned int>(pythonArgv.attr("__len__")());
   std::vector<char*> argv(argc);

   for ( unsigned int i = 0; i < argc; ++i )
   {
      argv[i] = bp::extract<char*>(pythonArgv[i]);
   }

   return OSG::osgInit(argc, &argv[0]);
}

boost::python::tuple calcViewRay(OSG::Camera* self, OSG::Int32 x,
                                 OSG::Int32 y, OSG::Viewport& port)
{
   OSG::Line line;
   bool result = self->calcViewRay(line, x, y, port);
   return boost::python::make_tuple(result, line);
}

boost::python::tuple getNormalizedCoordinates(OSG::Viewport* self,
                                              const OSG::Int32 vpX,
                                              const OSG::Int32 vpY)
{
   OSG::Real32 norm_x, norm_y;
   self->getNormalizedCoordinates(norm_x, norm_y, vpX, vpY);
   return boost::python::make_tuple(norm_x, norm_y);
}

} // namespace osgwrap

// Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#if defined(_WIN32)
# ifdef __MWERKS__
#  pragma ANSI_strict off
# endif
# include <windows.h>
# ifdef __MWERKS__
#  pragma ANSI_strict reset
# endif

# ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable:4297)
#  pragma warning(disable:4535)
extern "C" void straight_to_debugger(unsigned int, EXCEPTION_POINTERS*)
{
   throw;
}
extern "C" void (*old_translator)(unsigned, EXCEPTION_POINTERS*)
         = _set_se_translator(straight_to_debugger);
#  pragma warning(pop)
# endif

#endif // _WIN32
